import { Component, ReactNode } from 'react';
import { connect } from 'react-redux';
import { 
    Breadcrumb, 
    Layout, 
    Flex, 
    ConfigProvider, 
    FloatButton, 
    Collapse, 
    Popconfirm, 
    InputNumber, 
    Dropdown, 
    Descriptions, 
    Form, 
    Tooltip, 
    Select, 
    Divider, 
    Table, 
    message, 
    Input, 
    Space, 
    Button 
} from "antd";
import type { MenuProps } from 'antd';
import { 
    EyeOutlined, 
    DeleteOutlined, 
    FileTextOutlined, 
    MoreOutlined,
    SendOutlined,
} from '@ant-design/icons';
import { TinyColor } from '@ctrl/tinycolor';
import type { FormProps } from 'antd';
import { encode } from 'base-64';
import { cloneDeep } from 'lodash';

import MarkdownView from '@comp/markdown/show';
import { 
    TABLE_VERSION_ITERATION_REQUEST_FIELDS, 
    TABLE_VERSION_ITERATION_FIELDS, 
    TABLE_MICRO_SERVICE_FIELDS,
    UNAME,
} from '@conf/db';
import { 
    getdayjs, 
    isStringEmpty 
} from '@rutil/index';
import { getPrjs } from '@act/project';
import { getVersionIterator, getOpenVersionIteratorsByPrj } from '@act/version_iterator';
import { 
    getVersionIteratorFolders, 
    delVersionIteratorFolder 
} from '@act/version_iterator_folders';
import { 
    getVersionIteratorRequestsByProject, 
    delVersionIteratorRequest, 
    setVersionIterationRequestSort,
    batchMoveIteratorRequest,
    batchSetProjectRequestFold,
} from '@act/version_iterator_requests';
import { langFormat, langTrans } from '@lang/i18n';

const { Header, Content, Footer } = Layout;

type FieldType = {
    prj?: string;
    folder?: string,
    title?: string;
    uri?: string;
};

const colorsAddRequestApi = ['#fc6076', '#ff9a44', '#ef9d43', '#e75516'];
const colorsSendRequestApi = ['#6253e1', '#04befe'];
const getHoverColors = (colors: string[]) =>
    colors.map((color) => new TinyColor(color).lighten(5).toString());
const getActiveColors = (colors: string[]) =>
    colors.map((color) => new TinyColor(color).darken(5).toString());

let version_iterator_uuid = TABLE_VERSION_ITERATION_FIELDS.FIELD_UUID;
let version_iterator_title = TABLE_VERSION_ITERATION_FIELDS.FIELD_NAME;
let iteration_request_sort = TABLE_VERSION_ITERATION_REQUEST_FIELDS.FIELD_SORT;
let version_iterator_prjs = TABLE_VERSION_ITERATION_FIELDS.FIELD_PROJECTS;
let version_iterator_content = TABLE_VERSION_ITERATION_FIELDS.FIELD_CONTENT;
let version_iterator_openflg = TABLE_VERSION_ITERATION_FIELDS.FIELD_OPENFLG;
let version_iterator_ctime = TABLE_VERSION_ITERATION_FIELDS.FIELD_CTIME;

let iteration_request_fold = TABLE_VERSION_ITERATION_REQUEST_FIELDS.FIELD_FOLD;
let iteration_request_prj = TABLE_VERSION_ITERATION_REQUEST_FIELDS.FIELD_MICRO_SERVICE_LABEL;
let iteration_request_method = TABLE_VERSION_ITERATION_REQUEST_FIELDS.FIELD_REQUEST_METHOD;
let iteration_request_uri = TABLE_VERSION_ITERATION_REQUEST_FIELDS.FIELD_URI;
let iteration_request_title = TABLE_VERSION_ITERATION_REQUEST_FIELDS.FIELD_TITLE;

let prj_label = TABLE_MICRO_SERVICE_FIELDS.FIELD_LABEL;
let prj_remark = TABLE_MICRO_SERVICE_FIELDS.FIELD_REMARK;

class RequestListVersion extends Component {

    constructor(props) {
        super(props);
        let iteratorId = this.props.match.params.id;
        this.state = {
            iteratorId,
            versionIteration: {},
            requestsJsxDividered: {},
            listColumn: [
                {
                    title: langTrans("prj doc table field1"),
                    dataIndex: iteration_request_uri,
                    width: 150,
                    render: (uri) => { 
                        if (uri.length > 50) {
                            return <Tooltip title={ uri } placement='right'>
                                {"..." + uri.substring(uri.length - 50, uri.length)}
                                </Tooltip>;
                        } else {
                            return uri;
                        }
                    }
                },
                {
                    title: langTrans("prj doc table field2"),
                    dataIndex: iteration_request_title,
                    width: 150,
                },
                {
                    title: langTrans("prj doc table field3"),
                    dataIndex: iteration_request_sort,
                    width: 50,
                    render: (sort, record) => {
                        let prj = record[iteration_request_prj];
                        let method = record[iteration_request_method];
                        let uri = record[iteration_request_uri];
                        if (sort === undefined) {
                            return <InputNumber style={{width: 65}} value={0} onBlur={event => this.setApiSort(prj, method, uri, event.target.value)} />;
                        } else {
                            return <InputNumber style={{width: 65}} value={sort} onBlur={event => this.setApiSort(prj, method, uri, event.target.value)} />;
                        }
                    }
                },
                {
                    title: langTrans("prj doc table field4"),
                    key: 'operater',
                    width: 50,
                    render: (_, record) => {
                        let docDetailUrl = "#/version_iterator_request/" + this.state.iteratorId + "/" + record[iteration_request_prj] + "/" + record[iteration_request_method] + "/" + encode(record[iteration_request_uri]);
                        let sendRequestUrl = "#/internet_request_send_by_api/" + this.state.iteratorId + "/" + record[iteration_request_prj] + "/" + record[iteration_request_method] + "/" + encode(record[iteration_request_uri]);
                        return (
                            <Space size="middle">
                                <Tooltip title={langTrans("prj doc table act1")}>
                                    <Button type="link" icon={<SendOutlined />} href={ sendRequestUrl } />
                                </Tooltip>
                                <Tooltip title={langTrans("prj doc table act2")}>
                                    <Button type="link" icon={<EyeOutlined />} href={ docDetailUrl } />
                                </Tooltip>
                                { this.state.versionIteration[version_iterator_openflg] === 1 ? 
                                <Dropdown menu={this.getMore(record)}>
                                    <Button type="text" icon={<MoreOutlined />} />
                                </Dropdown>
                                : null}
                            </Space>
                        );
                    },
                }
            ],
            formReadyFlg: false,
            folders: [],
            prj: "",
            folder: null,
            movedRequests: [],
        }
    }

    async componentWillReceiveProps(nextProps) {
        let iteratorId = nextProps.match.params.id;
        if (this.state.iteratorId !== iteratorId) {
            let versionIteration = await getVersionIterator(iteratorId);
            this.setState( { iteratorId, versionIteration }, () => this.onFinish({}) );
        }
    }

    componentDidMount() {
        if(this.props.prjs.length === 0) {
            getPrjs(this.props.dispatch);
        }
        this.onFinish({});
        getVersionIterator(this.state.iteratorId).then(versionIteration => this.setState( { versionIteration, formReadyFlg : true } ));
    }

    setApiSort = async (prj : string, method : string, uri : string, sort : number) => {
        setVersionIterationRequestSort(this.state.iteratorId, prj, method, uri, sort, () => {
            this.onFinish({
                prj: this.state.prj,
                folder: this.state.folder,
            });
        });
    }

    setMovedRequests = newMovedRequestKeys => {
        this.state.movedRequests = newMovedRequestKeys;
        this.onFinish({
            prj: this.state.prj,
            folder: this.state.folder,
        });
    }

    getMore = (record : any) : MenuProps => {
            return {'items': [{
                key: "1",
                danger: true,
                label: <Popconfirm
                    title={langTrans("prj doc del title")}
                    description={langTrans("prj doc del desc")}
                    onConfirm={e => {
                        delVersionIteratorRequest(record, ()=>{
                            this.onFinish({});
                        });
                    }}
                    okText={langTrans("prj doc del sure")}
                    cancelText={langTrans("prj doc del cancel")}
                >
                    <Button danger type="link" icon={<DeleteOutlined />} />
                </Popconfirm>,
            }]};
    }

    onFinish: FormProps<FieldType>['onFinish'] = async (values) => {
        let prj = values?.prj;
        let title = values?.title;
        let uri = values?.uri;
        let folder = values?.folder;
        let version_iteration_requests = await getVersionIteratorRequestsByProject(this.state.iteratorId, prj, folder, title, uri);
        let requestsDividered : any = {};
        let requestsJsxDividered : any = {};
        
        for(let version_iteration_request of version_iteration_requests ) {
            version_iteration_request.key = version_iteration_request[iteration_request_method] + "$$" + version_iteration_request[iteration_request_uri];
            let prj = version_iteration_request[iteration_request_prj];
            if (!(prj in requestsDividered)) {
                requestsDividered[prj] = {};
                requestsJsxDividered[prj] = [];
                let versionIterators = (await getOpenVersionIteratorsByPrj(prj))
                .filter(item => item[version_iterator_uuid] != this.state.iteratorId)
                .map(item => {
                    return {value: item[version_iterator_uuid], label: item[version_iterator_title]}
                });
                requestsJsxDividered[prj]['__iterators'] = versionIterators;
                requestsJsxDividered[prj]['__requests'] = [];
                let folders = await getVersionIteratorFolders(this.state.iteratorId, prj);
                let oldFolders = this.state.folders;
                oldFolders[prj] = folders;
            }
            let fold = version_iteration_request[iteration_request_fold];
            if (!(fold in requestsDividered[prj])) {
                requestsDividered[prj][fold] = [];

                let foldJsx = {};
                foldJsx.key = fold;
                foldJsx.label = "/" + fold;
                foldJsx.children = (<Table 
                    rowSelection={{selectedRowKeys: this.state.movedRequests, onChange: this.setMovedRequests}}
                    dataSource={requestsDividered[prj][fold]} 
                    columns={this.state.listColumn} 
                />);
                foldJsx.extra = ((!isStringEmpty(fold) && this.state.versionIteration[version_iterator_openflg] === 1) ? (
                <DeleteOutlined onClick={event => {
                    delVersionIteratorFolder(this.state.iteratorId, prj, fold, async ()=>{
                        message.success("删除文件夹成功");
                        let folders = await getVersionIteratorFolders(this.state.iteratorId, prj);
                        let oldFolders = this.state.folders;
                        oldFolders[prj] = folders;
                        this.setState({folders: cloneDeep(this.state.folders)});
                        this.onFinish({});
                    });
                    event.stopPropagation();
                }} />) : null);

                requestsJsxDividered[prj]['__requests'].push(foldJsx);
            }
            requestsDividered[prj][fold].push(version_iteration_request);
        }
        for (let _prj in requestsJsxDividered) {
            for (let requestJsxDividered of requestsJsxDividered[_prj]) {
                let fold = requestJsxDividered.key;
                requestJsxDividered.label = "/" + fold + "（" + requestsDividered[_prj][fold].length + "）";
            }
        }
        this.setState({
            requestsJsxDividered,
            prj,
            folder
        });
    }

    render() : ReactNode {

        return (
            <Layout>
                <Header style={{ padding: 0 }}>
                    {langTrans("version doc title")}
                </Header>
                {this.state.formReadyFlg ?
                <Content style={{ padding: '0 16px', width: "calc(100% - 16px)" }}>
                    <Breadcrumb style={{ margin: '16px 0' }} items={[
                        { title: langTrans("version doc bread1") }, 
                        { title: langTrans("version doc bread2") }
                    ]} />
                    <Descriptions column={2} title={langTrans("version doc desc title")} items={ [
                        {
                            key: version_iterator_title,
                            label: langTrans("version doc desc1"),
                            children: this.state.versionIteration[version_iterator_title],
                        },
                        {
                            key: version_iterator_openflg,
                            label: langTrans("version doc desc2"),
                            children: this.state.versionIteration[version_iterator_openflg] === 1 ? langTrans("version doc status1") : langTrans("version doc status2"),
                        },
                        {
                            key: UNAME,
                            label: langTrans("version doc desc3"),
                            children: this.state.versionIteration[UNAME],
                        },
                        {
                            key: version_iterator_ctime,
                            label: langTrans("version doc desc4"),
                            children: getdayjs(this.state.versionIteration[version_iterator_ctime]).format("YYYY-MM-DD"),
                        },
                        ] } />
                    <Flex justify="flex-start" align="center" gap="middle">
                        <Form 
                            layout="inline"
                            onFinish={ this.onFinish } 
                            initialValues={ { prj: this.state.prj } }
                            autoComplete="off"
                        >
                            <Form.Item<FieldType> style={{paddingBottom: 20}} label={langTrans("prj doc operator1")} name="uri" rules={[{ required: false }]}>
                                <Input />
                            </Form.Item>

                            <Form.Item<FieldType> label={langTrans("prj doc operator2")} name="title" rules={[{ required: false }]}>
                                <Input />
                            </Form.Item>

                            <Form.Item<FieldType> label={langTrans("version doc operator1")} name="prj" rules={[{ required:  false }]}>
                                <Select
                                    style={{ width: 180 }}
                                    options={this.state.versionIteration[version_iterator_prjs].map(item => {
                                        return {value: item, label: this.props.prjs.find(row => row[prj_label] === item) ? this.props.prjs.find(row => row[prj_label] === item)[prj_remark] : ""}
                                    })}
                                    onChange={ async value => {
                                        this.setState({ prj: value });
                                    } }
                                />
                            </Form.Item>                           

                            <Form.Item<FieldType> label={langTrans("version doc operator2")} name="folder" rules={[{ required:  false }]}>
                                <Select
                                    style={{ width: 180 }}
                                    options={ this.state.folders[this.state.prj] }
                                />
                            </Form.Item>

                            <Form.Item wrapperCol={{ offset: 8, span: 16 }}>
                                <Button htmlType="submit">
                                    {langTrans("prj doc btn")}
                                </Button>
                            </Form.Item>
                        </Form>
                        <Flex vertical justify="flex-start" align="center" gap="middle">
                            <ConfigProvider
                                theme={{
                                    components: {
                                    Button: {
                                        colorPrimary: `linear-gradient(90deg,  ${colorsAddRequestApi.join(', ')})`,
                                        colorPrimaryHover: `linear-gradient(90deg, ${getHoverColors(colorsAddRequestApi).join(', ')})`,
                                        colorPrimaryActive: `linear-gradient(90deg, ${getActiveColors(colorsAddRequestApi).join(', ')})`,
                                        lineWidth: 0,
                                    },
                                    },
                                }}
                                >
                                <Button type="primary" href={'#/interator_add_request/' + this.state.iteratorId} size="large">
                                    {langTrans("version doc btn2")}
                                </Button>
                            </ConfigProvider>

                            <ConfigProvider
                                theme={{
                                    components: {
                                    Button: {
                                        colorPrimary: `linear-gradient(135deg,  ${colorsSendRequestApi.join(', ')})`,
                                        colorPrimaryHover: `linear-gradient(135deg, ${getHoverColors(colorsSendRequestApi).join(', ')})`,
                                        colorPrimaryActive: `linear-gradient(135deg, ${getActiveColors(colorsSendRequestApi).join(', ')})`,
                                        lineWidth: 0,
                                    },
                                    },
                                }}
                                >
                                <Button type="primary" href={'#/internet_request_send_by_iterator/' + this.state.iteratorId} size="large">
                                    {langTrans("version doc btn1")}
                                </Button>
                            </ConfigProvider>

                        </Flex>
                    </Flex>
                    {Object.keys(this.state.requestsJsxDividered).map(prj => (
                        (this.props.prjs.length > 0 && this.props.prjs.find(row => row[prj_label] === prj) ? 
                            <div key={prj}>
                                <Divider orientation="left">
                                    <p>{langFormat("version doc project", {
                                        name: (this.props.prjs.length > 0 ? this.props.prjs.find(row => row[prj_label] === prj)[prj_remark] : "")
                                    })}</p >
                                </Divider>
                                <Form layout="inline" style={{marginBottom: 16}}>
                                    <Form.Item label={langTrans("version doc operator3")}>
                                        <Select
                                            style={{minWidth: 130}}
                                            onChange={ value => {
                                                batchMoveIteratorRequest(this.state.iteratorId, prj, this.state.movedRequests, value, () => {
                                                    this.state.movedRequests = [];
                                                    message.success("移动迭代成功");
                                                    this.onFinish({
                                                        prj: this.state.prj,
                                                        folder: this.state.folder,
                                                    });
                                                });
                                            }}
                                            options={ this.state.requestsJsxDividered[prj]['__iterators'] }
                                        />
                                    </Form.Item>
                                    <Form.Item label={langTrans("version doc operator4")}>
                                        <Select
                                            style={{minWidth: 130}}
                                            onChange={ async value => {
                                                await batchSetProjectRequestFold(this.state.iteratorId, prj, this.state.movedRequests, value);
                                                this.state.movedRequests = [];
                                                this.onFinish({
                                                    title: this.state.title, 
                                                    uri: this.state.uri
                                                });
                                            } }
                                            dropdownRender={(menu) => (
                                                <>
                                                    {menu}
                                                    <Divider style={{ margin: '8px 0' }} />
                                                    <Input
                                                        placeholder="回车新建文件夹"
                                                        onKeyDown={e => {
                                                            if (e.key === 'Enter') {
                                                                this.handleCreateFolder(e.target.value);
                                                                e.target.value = ""
                                                            }
                                                            e.stopPropagation()
                                                        }}
                                                    />
                                                </>
                                            )}
                                            options={ this.state.folders[prj] }
                                        />
                                    </Form.Item>
                                </Form>
                                <Collapse items={this.state.requestsJsxDividered[prj]['__requests']} />
                            </div>
                        : null)
                    ))}
                    <Flex>
                        <Divider>{langTrans("version doc md title")}</Divider>
                    </Flex>
                    <MarkdownView 
                        showNav={ true } 
                        content={ this.state.versionIteration[version_iterator_content] } show={ this.state.formReadyFlg } 
                        width={ 630 }
                        />
                    <FloatButton 
                        icon={<FileTextOutlined />}
                        description={langTrans("doc btn1")}
                        shape="square"
                        style={{right: 24, width: 60}}
                        onClick={() => window.location.href = "#/version_iterator_doc/" + this.state.iteratorId} />
                </Content>
                : null}
                <Footer style={{ textAlign: 'center' }}>
                ApiChain ©{new Date().getFullYear()} Created by 方海亮
                </Footer>
            </Layout>
        );
    }
}
    
function mapStateToProps (state) {
    return {
        prjs: state.prj.list
    }
}
      
export default connect(mapStateToProps)(RequestListVersion);